#include "spl.includes.h"
#include "splib.h"

using namespace SPLib::Settings;

#define MAX_DOUBLE_LENGTH 20

RegistrySettings::RegistrySettings(PCTSTR szLocation)
    : SettingsBase(szLocation), hKey(NULL)
{
}

RegistrySettings::~RegistrySettings()
{
    // close settings registry key
    RegCloseKey(hKey);
}

BOOL RegistrySettings::init()
{
    // open/create settings registry key
    return RegCreateKeyEx(HKEY_CURRENT_USER, getLocation(), 0, NULL,
        0, KEY_READ | KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS;
}

BOOL RegistrySettings::getSetting(PCTSTR szName,
    PTSTR __out *value, DWORD __out *dwSize)
{
    // get cstring value
    return RegQueryValueEx(hKey, szName, NULL, NULL,
        (PBYTE)*value, dwSize) == ERROR_SUCCESS;
}

BOOL RegistrySettings::getSetting(PCTSTR szName, LONG __out *value)
{
    // value size
    DWORD dwSize = (DWORD)sizeof(LONG);
    // get long value
    return RegQueryValueEx(hKey, szName, NULL, NULL,
        (PBYTE)value, &dwSize) == ERROR_SUCCESS;
}

BOOL RegistrySettings::getSetting(PCTSTR szName, INT __out *value)
{
    // value size
    DWORD dwSize = (DWORD)sizeof(INT);
    // get integer value
    return RegQueryValueEx(hKey, szName, NULL, NULL,
        (PBYTE)value, &dwSize) == ERROR_SUCCESS;
}

BOOL RegistrySettings::getSetting(PCTSTR szName, DOUBLE __out *value)
{
    // value as cstring
    PTCHAR pszValue;
    // value length
    DWORD dwLength;

    // get cstring value, abort if failure
    if (!getSetting(szName, &pszValue, &dwLength)) return FALSE;

    // convert value into double
    *value = _ttof(pszValue);

    // operation successfull
    return TRUE;
}

BOOL RegistrySettings::setSetting(PCTSTR szName,
    PCTSTR __in value, DWORD __in dwSize)
{
    // set cstring value
    return RegSetValueEx(hKey, szName, 0, REG_SZ,
        (PBYTE)value, dwSize) == ERROR_SUCCESS;
}

BOOL RegistrySettings::setSetting(PCTSTR szName, LONG __in value)
{
    // set long value
    return RegSetValueEx(hKey, szName, 0, REG_QWORD,
        (PBYTE)&value, sizeof(value)) == ERROR_SUCCESS;
}

BOOL RegistrySettings::setSetting(PCTSTR szName, INT __in value)
{
    // set integer value
    return RegSetValueEx(hKey, szName, 0, REG_DWORD,
        (PBYTE)&value, sizeof(value)) == ERROR_SUCCESS;
}

BOOL RegistrySettings::setSetting(PCTSTR szName, DOUBLE __in value)
{
    // value as cstring
    TCHAR szValue[MAX_DOUBLE_LENGTH + 1];

    // set cstring converted decimal value
    return setSetting(szName, szValue,
        _stprintf(szValue, _T("%.10f"), value) + 1);
}